import asyncio
import re
from langchain_core.tools import tool
from MCPService.webService import get_webService_client
import logging

# 初始化日志
logger = logging.getLogger(__name__)


# 定义query格式校验函数
def validate_query_format(query: str) -> tuple[bool, str]:
    """
    校验查询参数的格式合法性
    返回值：(是否合法, 错误信息/空字符串)
    """
    # 检查是否为空
    if not query or query.strip() == "":
        return False, "查询关键词不能为空，请提供有效的搜索内容"

    # 检查长度（避免过长查询）
    if len(query) > 500:
        return False, f"查询内容过长（当前{len(query)}字符），请控制在500字符以内"

    # 检查是否包含非法字符（可能导致JSON解析失败的字符）
    invalid_chars = re.findall(r'[\\`"\'\r\n]+', query)
    if invalid_chars:
        return False, f"查询包含非法字符：{set(invalid_chars)}，请移除后重试"

    return True, ""


# 定义核心异步搜索函数
async def web_service_async(query: str) -> str:
    "调用阿里云百炼 Web 搜索工具（bailian_web_search），获取实时信息"
    try:
        # 1. 先执行格式校验
        is_valid, error_msg = validate_query_format(query)
        if not is_valid:
            logger.warning(f"查询格式校验失败：{error_msg}，query={query}")
            return error_msg

        # 2. 异步获取客户端
        client = await get_webService_client()
        if not client:
            return "搜索客户端初始化失败"

        # 3. 异步获取工具列表并筛选
        tools = await client.get_tools()
        search_tool = next((t for t in tools if t.name == "bailian_web_search"), None)
        if not search_tool:
            logger.error("未在客户端工具列表中找到 'bailian_web_search'")
            return "未找到指定搜索工具，无法执行搜索"

        # 4. 异步调用工具（带超时）
        try:
            result = await asyncio.wait_for(
                search_tool.ainvoke({"query": query}),
                timeout=15.0  # 15秒超时
            )
        except asyncio.TimeoutError:
            return "搜索超时（超过15秒），请稍后重试"

        # 5. 处理结果
        if not result:
            return "未获取到搜索结果，建议简化关键词或更换查询方向"

        # 提取有效内容
        if isinstance(result, dict):
            content = result.get("answer", result.get("content", str(result)))
        else:
            content = str(result)

        # 截断过长内容
        return f"搜索结果：{content[:800]}"

    except Exception as e:
        logger.error(f"Web搜索调用全流程异常：{str(e)}", exc_info=True)
        return "搜索服务暂时不可用，请稍后再试（如问题持续，可检查网络或服务配置）"


# 用@tool装饰器定义LangChain工具
@tool(
    "web_service",
    description="用于搜索实时网络信息，仅需提供query参数（查询关键词），适用于获取最新资讯、数据等内容。"
                "query需满足：非空、长度≤500字符、不包含\\、`、\"、'、换行符等特殊字符。"
)
async def web_search_aliyun(query: str) -> str:
    return await web_service_async(query)


# 同步包装函数
def web_search_aliyun_sync(query: str) -> str:
    return asyncio.run(web_service_async(query))


# 工具列表导出函数
def get_chat_tools() -> list:
    return [web_search_aliyun]